﻿package com.floorplanner.lib3ds
{
	import com.floorplanner.lib3ds.*;
	import com.floorplanner.lib3ds.data.Lib3dsUserData;
	
	public class Lib3dsMaterial extends Lib3dsCore
	{
		public var user:Lib3dsUserData;
		public var next:Lib3dsMaterial;
		public var name:String; //[64];
		public var ambient:Lib3dsRgba;
		public var diffuse:Lib3dsRgba;
		public var specular:Lib3dsRgba;
		public var shininess:Number;
		public var shin_strength:Number;
		public var use_blur:Boolean;
		public var blur:Number;
		public var transparency:Number;
		public var falloff:Number;
		public var additive:Boolean;
		public var use_falloff:Boolean;
		public var self_illum:Boolean;
		public var shading:int;
		public var soften:Boolean;
		public var face_map:Boolean;
		public var two_sided:Boolean;
		public var map_decal:Boolean;
		public var use_wire:Boolean;
		public var use_wire_abs:Boolean;
		public var wire_size:Number;
		public var texture1_map:Lib3dsTextureMap;
		public var texture1_mask:Lib3dsTextureMap;
		public var texture2_map:Lib3dsTextureMap;
		public var texture2_mask:Lib3dsTextureMap;
		public var opacity_map:Lib3dsTextureMap;
		public var opacity_mask:Lib3dsTextureMap;
		public var bump_map:Lib3dsTextureMap;
		public var bump_mask:Lib3dsTextureMap;
		public var specular_map:Lib3dsTextureMap;
		public var specular_mask:Lib3dsTextureMap;
		public var shininess_map:Lib3dsTextureMap;
		public var shininess_mask:Lib3dsTextureMap;
		public var self_illum_map:Lib3dsTextureMap;
		public var self_illum_mask:Lib3dsTextureMap;
		public var reflection_map:Lib3dsTextureMap;
		public var reflection_mask:Lib3dsTextureMap;
		public var autorefl_map:Lib3dsAutoReflMap;  
		
		public function Lib3dsMaterial()
		{
			
		}

		public function read( io:Lib3dsIO ):Boolean
		{
			var c:Lib3dsChunk = Lib3dsChunk.read( io );
			var chunk:uint = 0;
			
			if( c.chunk != Lib3dsChunk.MAT_ENTRY )
			{
				return false;
			}
			
			chunk = c.next( io );
			while( chunk != 0 )
			{
				switch( chunk )
				{
					case Lib3dsChunk.MAT_NAME:
						this.name = io.readString();	
						debug( "Lib3dsMaterial: " + this.name );
						break;
						
					case Lib3dsChunk.MAT_AMBIENT:
						c.reset( io );
						this.ambient = this.readColor( io );
						debug("\tMAT_AMBIENT: " + this.ambient );
						break;
						
					case Lib3dsChunk.MAT_DIFFUSE:
						c.reset( io );
						this.diffuse = readColor( io );
						debug("\tMAT_DIFFUSE: " + this.diffuse );
						break;
						
					case Lib3dsChunk.MAT_SPECULAR:
						c.reset( io );
						this.specular = readColor( io );
						debug("\tMAT_SPECULAR: " + this.specular );
						break;
						
					case Lib3dsChunk.MAT_SHININESS:
						c.reset( io );
						this.shininess = io.readPercentage();
						debug("\tMAT_SHININESS: " + this.shininess );
						break;
					case Lib3dsChunk.MAT_SHIN2PCT:
						c.reset( io );
						this.shin_strength = io.readPercentage();
						debug("\tMAT_SHIN2PCT: " + this.shin_strength );
						break;
					case Lib3dsChunk.MAT_TRANSPARENCY:
						c.reset( io );
						this.transparency = io.readPercentage();
						debug("\tMAT_TRANSPARENCY: " + this.transparency );
						break;
					case Lib3dsChunk.MAT_XPFALL:
						c.reset( io );
						this.falloff = io.readPercentage();
						debug("\tfalloff: " + this.falloff );
						break;
					case Lib3dsChunk.MAT_USE_XPFALL:
						debug("\tuse_falloff = true");
						this.use_falloff = true;
						break;
					case Lib3dsChunk.MAT_REFBLUR:
						c.reset( io );
						this.blur = io.readPercentage();
						debug("\tMAT_REFBLUR: " + this.blur );
						break;
					case Lib3dsChunk.MAT_USE_REFBLUR:
						debug("\tMAT_USE_REFBLUR = true");
						this.use_blur = true;
						break;
					case Lib3dsChunk.MAT_SHADING:
						this.shading = io.readShort();
						debug("\tMAT_SHADING: " + this.shading);
						break;
					case Lib3dsChunk.MAT_SELF_ILLUM:
						this.self_illum = true;
						break;
					case Lib3dsChunk.MAT_TWO_SIDE:
						this.two_sided = true;
						break;
					case Lib3dsChunk.MAT_DECAL:
						debug("\tMAT_DECAL = true");
						this.map_decal = true;
						break;
					case Lib3dsChunk.MAT_ADDITIVE:
						debug("\tMAT_ADDITIVE = true");
						this.additive = true;
						break;
					case Lib3dsChunk.MAT_FACEMAP:
						debug("\tMAT_FACEMAP = true");
						this.face_map = true;
						break;
					case Lib3dsChunk.MAT_PHONGSOFT:
						debug("\tMAT_PHONGSOFT = true");
						this.soften = true;
						break;
					case Lib3dsChunk.MAT_WIRE:
						this.use_wire = true;
						break;
					case Lib3dsChunk.MAT_WIREABS:
						this.use_wire_abs = true;
						break;
					case Lib3dsChunk.MAT_WIRE_SIZE:
						this.wire_size = io.readFloat();
						debug("\tMAT_WIRE_SIZE: " + this.wire_size);
						break;
					case Lib3dsChunk.MAT_TRANSFALLOFF_IN:
						debug("\tMAT_TRANSFALLOFF_IN");
						break;
					case Lib3dsChunk.MAT_TEXMAP:
						debug("\tMAT_TEXMAP");
						c.reset( io );
						this.texture1_map = readTexture( io );
						break;							
					case Lib3dsChunk.MAT_TEXMASK:
						c.reset( io );
						this.texture1_mask = readTexture( io );
						break;
					case Lib3dsChunk.MAT_TEX2MAP:
						c.reset( io );
						this.texture2_map = readTexture( io );
						break;
					case Lib3dsChunk.MAT_TEX2MASK:
						c.reset( io );
						this.texture2_mask = readTexture( io );
						break;
					case Lib3dsChunk.MAT_OPACMAP:
						c.reset( io );
						this.opacity_map = readTexture( io );
						break;							
					case Lib3dsChunk.MAT_OPACMASK:
						c.reset( io );
						this.opacity_mask = readTexture( io );
						break;							
					case Lib3dsChunk.MAT_BUMPMAP:
						c.reset( io );
						this.bump_map = readTexture( io );
						break;
					case Lib3dsChunk.MAT_BUMPMASK:
						c.reset( io );
						this.bump_mask = readTexture( io );
						break;
					case Lib3dsChunk.MAT_SPECMAP:
						c.reset( io );
						this.specular_map = readTexture( io );
						break;
					case Lib3dsChunk.MAT_SPECMASK:
						c.reset( io );
						this.specular_mask = readTexture( io );
						break;							
					case Lib3dsChunk.MAT_SHINMAP:
						c.reset( io );
						this.shininess_map = readTexture( io );
						break;							
					case Lib3dsChunk.MAT_SHINMASK:
						c.reset( io );
						this.shininess_mask = readTexture( io );
						break;
					case Lib3dsChunk.MAT_SELFIMAP:
						c.reset( io );
						this.self_illum_map = readTexture( io );
						break;
					case Lib3dsChunk.MAT_SELFIMASK:
						c.reset( io );
						this.self_illum_mask = readTexture( io );
						break;
					case Lib3dsChunk.MAT_REFLMAP:
						c.reset( io );
						this.reflection_map = readTexture( io );
						break;	
					case Lib3dsChunk.MAT_REFLMASK:
						c.reset( io );
						this.reflection_mask = readTexture( io );
						break;
					case Lib3dsChunk.MAT_ACUBIC:
						break;
					default:
						debug("readMaterial -> unknown chunk: 0x" + chunk.toString(16) );
						break;
				}
				chunk = c.next( io );
			}
			
		
			io.position = c.end;
			
			return true;	
		}
		
		/**
		 * 
		 * @return
		 */
		private function readColor( io:Lib3dsIO ):Lib3dsRgba
		{
			var c:Lib3dsChunk = Lib3dsChunk.read( io );
			var chunk:uint = 0;
			var i:int, j:int;
			var haveLin:Boolean = false;
			var rgba:Array = new Array();
			
			debug( "readColor" );
						
			chunk = c.next( io );
			while( chunk != 0 )
			{
				switch( chunk )
				{
					case Lib3dsChunk.LIN_COLOR_24:
						rgba = [];
						for( i = 0; i < 3; ++i ) 
						{
							rgba.push( io.readUnsignedByte() );
						}
						haveLin = true;
						break;
					case Lib3dsChunk.COLOR_24:
						if( !haveLin )
						{
							rgba = [];
							for( i = 0; i < 3; ++i ) 
							{
								rgba.push( io.readUnsignedByte() );
							}
						}
						break;
					default:
						debug("readColor -> unknown chunk: 0x" + chunk.toString(16) );
						break;
				}
 				chunk = c.next( io );
			}
			c.readEnd( io );
			return new Lib3dsRgba( rgba[0], rgba[1], rgba[2], 255.0 );
		}
				
		/**
		 * 
		 * @return
		 */
		private function readTexture( io:Lib3dsIO ):Lib3dsTextureMap
		{
			var lTexture:Lib3dsTextureMap = new Lib3dsTextureMap();
			lTexture.read( io );
			return lTexture;
		}
	}
}
